﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
		<title>User management - 用户管理</title>
		<link type="text/css" rel="stylesheet" href="../bootstrap.min.css" />
	</head>

	<body>

		<div class="document-contents">

			<h3>User Entity - 用户实体</h3>
			<p>User entity represents a <strong>user of the application</strong>. It should be derived from 
				<strong>AbpUser</strong> class as shown below:</p>
			<p class="translation">用户实体代表了应用程序中的一个用户。它应该从 <strong>AbpUser</strong> 类派生，如下所示：</p>
			<pre lang="cs">public class User : AbpUser&lt;Tenant, User&gt;
{
    //add your own user properties here - 在这里添中你自己的用户属性
}</pre>
			<p>This class is created when you <a href="/Pages/Documents/Zero/Installation">install</a> module-zero. 
Users are stored in <strong>AbpUsers</strong> table in the database. You can add 
your custom properties to User class (and create database migrations for the 
changes).</p>
			<p class="translation">
				这个类是你在安装 <a href="Installation.html">module-zero</a> 时被创建的。
				用户数据被存储在数据库中的 <strong>AbpUsers</strong> 表。
				你可以向 User 类中添加自定义属性（以及为这些改变创建数据库迁移）。
			</p>
			<p>AbpUser class defines some base properties. Some of the properties are:</p>
			<p class="translation">AbpUser 类定义了一些基本属性。部分属性如下：</p>
			<ul>
				<li>
					<strong>UserName</strong>: Login name of the user Should be <strong>
	unique</strong> for a <a href="/Pages/Documents/Zero/Tenant-Management">
	tenant</a>.</li>
				<p class="translation">
					<strong>UserName</strong>：用户的登录名称，对于一个<a href="Tenant-Management">租户</a>来说应该是唯一的。
				</p>
				<li>
					<strong>EmailAddress</strong>: Email address of the user. Should be
					<strong>unique</strong> for a
					<a href="/Pages/Documents/Zero/Tenant-Management">tenant</a>.</li>
				<p class="translation">
					<strong>EmailAddress</strong>：用户的 Eamil 地址。对于一个<a href="Tenant-Management">租户</a>来说应该是唯一的。
				</p>
				<li>
					<strong>Password</strong>: Hashed password of the user.</li>
				<p class="translation">
					<strong>Password</strong>：用户的哈希密码。
				</p>
				<li>
					<strong>IsActive</strong>: True, if this user can login to the 
	application.</li>
				<p class="translation"><strong>IsActive</strong>：如果用户可以登录到应用程序则为 True。</p>
				<li>
					<strong>Name</strong> and <strong>Surname</strong> of the user.</li>
				<p class="translation">
					<strong>Name</strong> 和 <strong>Surname</strong>：用户的名字和姓氏。
				</p>
			</ul>
			<p>There are also some properties like <strong>Roles</strong>, <strong>
Permissions</strong>, <strong>Tenant</strong>, <strong>Settings</strong>,
				<strong>IsEmailConfirmed</strong> and so on. Check AbpUser class for more 
information.</p>
			<p class="translation">
				还有一些属性，如 <strong>Roles</strong>, <strong>Permissions</strong>, <strong>Tenant</strong>, <strong>Settings</strong>, <strong>IsEmailConfirmed</strong> 等。
				你可以在 AbpUser 类中查看更多信息。
			</p>
			<p>AbpUser class is inherited from <strong>FullAuditedEntity</strong>. That means it has creation, modification and deletion audit properties. It's also 
				<strong>
					<a href="/Pages/Documents/Data-Filters#DocSoftDelete">Soft-Delete</a>
				</strong>. So, when we delete a 
user, it's not deleted from database, just marked as deleted.</p>
			<p class="translation">
				AbpUser 类是继承自 <strong>FullAuditedEntity</strong>。
				这意味着它拥有创建，修改及删除等审计属性。它还支持<a href="../Data-Filters.html#DocSoftDelete">软删除</a>。
				因此，当我们删除一个用户的时候，实际上它并没有从数据库中删除，而是仅仅标记为已删除。
			</p>
			<p>AbpUser class implements
				<a href="/Pages/Documents/Data-Filters#DocMayHaveTenant">IMayHaveTenant</a> 
filter to properly work in a multi-tenant application.</p>
			<p class="translation">
				为了在一个多租户的应用程序中更好地工作，AbpUser 类实现了 <a href="../Data-Filters.html#DocMayHaveTenant">IMayHaveTenant</a> 过滤器。
			</p>
			<p>Finally, <strong>Id</strong> of the User is defined as <strong>long</strong>.</p>
			<p class="translation">最后，用户的 <strong>Id</strong> 被定义为 <strong>long</strong> 类型。</p>
			<h3>User Manager - 用户管理器</h3>
			<p>
				<strong>UserManager </strong>is a service to perform <strong>domain logic</strong> 
for users:</p>
			<p class="translation">用户<strong>管理器</strong>是为用户执行<strong>领域逻辑</strong>的服务。</p>
			<pre lang="cs">public class UserManager : AbpUserManager&lt;Tenant, Role, User&gt;
{
    //...
}</pre>
			<p>You can <a href="/Pages/Documents/Dependency-Injection">inject</a> and use 
UserManager to create, delete, update users, grant permissions, change roles for 
users and much more. You can add your own methods here. Also, you can
				<strong>override</strong> any method of <strong>AbpUserManager</strong> base class for your own needs.</p>
			<p class="translation">
				你可以<a href="../Dependency-Injection.html">注入</a>并使用 UserManager 来创建，删除，更新用户,为用户授权，改变用户的角色以及更多操作。
				你可以在这里添加你自己的方法。并且，你可以<strong>重写</strong> <strong>AbpUserManager</strong> 基类的任何方法来满足你自己的需要。
			</p>
			<h4>Multi Tenancy - 多租户</h4>
			<p>
				<em>If you're not creating a multi-tenant application, you can skip this 
section. See <a href="../Multi-Tenancy.html">multi-tenancy 
documentation</a> for more information about multi-tenancy.</em>
			</p>
			<p class="translation">
				<em>
					如果你创建的不是一个多租户应用，那么你可以跳过本节。
					有关多租户的更多信息请阅读<a href="../Multi-Tenancy.html">多租户文档</a>。
				</em>
			</p>
			<p>UserManager is designed to work for a <strong>single tenant</strong> in a 
time. It works for the <strong>current tenant</strong> as default. Let's see 
some usages of the UserManager:</p>
			<p class="translation">
				UserManager 被设计来工作在<strong>单租户</strong>环境。它以<strong>当前租户</strong>作为默认来进行工作。让我们来看看 UserManager 的一些用法：
			</p>
			<pre lang="cs">public class MyTestAppService : ApplicationService
{
    private readonly UserManager _userManager;

    public MyTestAppService(UserManager userManager)
    {
        _userManager = userManager;
    }

    public void TestMethod_1()
    {
        //Find a user by email for current tenant - 为当前租户通过 email 来查找用户
        var user = <strong>_userManager.FindByEmail(&quot;sampleuser@aspnetboilerplate.com&quot;);</strong>
    }

    public void TestMethod_2()
    {
        //Switch to tenant 42 - 切换至租户 42
        CurrentUnitOfWork.<strong>SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, 42);</strong>

        //Find a user by email for the tenant 42 - 为租户 42 通过 email 来查找用户
        var user = _userManager.FindByEmail(&quot;sampleuser@aspnetboilerplate.com&quot;);
    }

    public void TestMethod_3()
    {
        //Disabling MayHaveTenant filter, so we can reach to all users - 禁用 MayHaveTenant 过滤器，因此我们可以搜索所有用户
        using (CurrentUnitOfWork.<strong>DisableFilter(AbpDataFilters.MayHaveTenant)</strong>)
        {
            //Now, we can search for a user name in all tenants - 现在，我们可以在所有租户中搜索用户名称
            var users = _userManager.Users.Where(u =&gt; u.UserName == &quot;sampleuser&quot;).ToList();

            //Or we can add TenantId filter if we want to search for a specific tenant - 或者，如果你想为特定租户进行搜索，我们可以添加 TenantId 过滤器
            var user = _userManager.Users.FirstOrDefault(u =&gt; u.TenantId == 42 &amp;&amp; u.UserName == &quot;sampleuser&quot;);
        }
    }
}</pre>
			<h4>User Login - 用户登录</h4>
			<p>Module-zero defines LoginManager which has a <strong>LoginAsync</strong> 
			method used to login to the application. It checks all logic for 
			login and returns a login result. LoginAsync method also <strong>automatically saves all login 
			attempts </strong>to the database (even it's a failed attempt). You 
			can use <strong>UserLoginAttempt</strong> entity to query it.</p>
			<p class="translation">
				Module-zero 定义了 LoginManager，它有一个 <strong>LoginAsync</strong> 方法用来登录到应用程序。
				它检查所有的登录逻辑并返回一个登录结果。
				LoginAsync 方法还<strong>自动保存所有登录尝试</strong>到数据库（甚至是一个失败的尝试）。
				你可以使用 <strong>UserLoginAttempt</strong> 实体来查询它。
			</p>
			<h4>About IdentityResults - 关于 IdentityResults</h4>
			<p>Some methods of UserManager return IdentityResult as a result instead of 
	throwing exceptions for some cases. This is nature of ASP.NET Identity 
	Framework. Module-zero also follows it. So, we should check this returning 
	result object to know if operation succeeded.</p>
			<p class="translation">
				UserManager 的一些方法返回了 IdentityResult 作为结果而不是抛出某种情况的异常。
				这是 ASP.NET Identity 框架的本质。Module-zero 也遵循它。
				所以，我们应该检查这个返回的结果对象就可知道操作是否成功。
			</p>
			<p>Module-zero defines <strong>CheckErrors</strong> extension method that 
	automatically checks errors and throws exception (a localized
				<a href="/Pages/Documents/Handling-Exceptions#DocShowUserFriendlyExceptions">
	UserFriendlyException</a>) if needed. Example usage:</p>
			<p class="translation">
				Module-zero 定义了 <strong>CheckErrors</strong> 扩展方法来自动地检查错误并在有需要时抛出异常（本地化 UserFriendlyException）。用法示例：
			</p>
			<pre lang="cs">(await UserManager.CreateAsync(user)).CheckErrors();</pre>
			<p>To get localized exceptions, we should provide a 
				<a href="/Pages/Documents/Localization">ILocalizationManager</a> 
	instance:</p>
			<p class="translation">
				想到得到本地化异常，我们需要提供一个 <a href="/Pages/Documents/Localization">ILocalizationManager</a> 实例。
			</p>
			<pre lang="cs">(await UserManager.CreateAsync(user)).CheckErrors(LocalizationManager);</pre>
			<h3>External Authentication - 外部认证</h3>
			<p>Login method of module-zero authenticate a user from the <strong>AbpUsers</strong> table in 
the database. Some applications may require to authenticate users from some 
external sources (like active directory, from another database's tables or even 
from a remote service).</p>
			<p class="translation">
				module-zero 的 Login 方法从数据库的 <strong>AbpUsers</strong> 表认证一个用户。
				有一些应用程序可能需要从一些外部源（像 Active Directory，从另外的数据库表或从远程服务）来认证用户。
			</p>
			<p>For such cases, UserManager defines an extension point named 'external 
authentication source'. We can create a class derived from <strong>
IExternalAuthenticationSource</strong> and register to the configuration. There 
is <strong>DefaultExternalAuthenticationSource</strong> class to simplify 
implementation of IExternalAuthenticationSource. Let's see an example:</p>
			<p class="translation">
				对于很多情况，UserManager 定义了一个名叫“外部认证源”的扩展点。
				我们可以创建一个从 <strong>IExternalAuthenticationSource</strong> 派生的类，并把它注册到配置中。
				有一个 <strong>DefaultExternalAuthenticationSource</strong> 类是 IExternalAuthenticationSource 的简单实现。
				让我们看下面的例子：
			</p>
			<pre lang="cs">public class MyExternalAuthSource : DefaultExternalAuthenticationSource&lt;Tenant, User&gt;
{
    public override string Name
    {
        get { return &quot;MyCustomSource&quot;; }
    }

    public override Task&lt;bool&gt; TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
    {
        //TODO: authenticate user and return true or false - 认证用户并返回 true 或 false
    }
}</pre>
			<p>In TryAuthenticateAsync method, we can check user name and password from some 
source and return true if given user is authenticated by this source. Also, we 
can override CreateUser and UpdateUser methods to control user creation and 
updating for this source.</p>
			<p class="translation">
				在 TryAuthenticateAsync 方法中，我们可以从这些源中检查用户名及密码，如果给定的用户通过了这个源的认证，那么返回 true。
				同时，我们可以重写 CreateUser 和 UpdateUser 方法来为这个源控制用户创建和更新。
			</p>
			<p>When a user authenticated by an external source, module-zero checks if this 
user does exists in the database (AbpUsers table). If not, it calls CreateUser 
to create the user, otherwise it calls UpdateUser to allow authentication source 
to update existing user informations.</p>
			<p class="translation">
				当通过外部源验证通过一个用户后，module-zero 会检查这个用户数据库（AbpUser 表）中是否存在该用户。
				如果不存在，就会调用 CreateUser 来创建该用户，否则调用 UpdateUser 来允许外部源去更新已存在的用户信息。
			</p>
			<p>We can define more than one external authentication source in an application. 
AbpUser entity has an AuthenticationSource property that shows which source 
authenticated this user.</p>
			<p class="translation">
				在一个应用程序中，我们可以定义多于一个的外部认证源。AbpUser 实体有一个 AuthenticationSource 属性，它表明了哪个源用来认证该用户。
			</p>
			<p>To register our authenciation source, we can use such a code in
				<a href="/Pages/Documents/Module-System">PreInitialize</a> of our module:</p>
			<p class="translation">
				想要注册我们的认证源，我们可以在模块的 <a href="../Module-System.html">PreInitialize</a> 中使用这些代码：
			</p>
			<pre lang="cs">Configuration.Modules.Zero().UserManagement.ExternalAuthenticationSources.Add&lt;MyExternalAuthSource&gt;();</pre>
			<h4>LDAP/Active Directory</h4>
			<p>LdapAuthenticationSource is an implementation of external authentication to 
make users login with their LDAP (active directory) user name and password.</p>
			<p class="translation">
				LdapAuthenticationSource 是一个外部认证的实现，它可以让用户使用他们的 LDAP（active directory）用户名和密码登录。
			</p>
			<p>If we want to use LDAP authentication, we first add 
				<a href="https://www.nuget.org/packages/Abp.Zero.Ldap" target="_blank">
Abp.Zero.Ldap</a> nuget 
package to our project (generally to Core (domain) project). Then we should extend 
				<strong>LdapAuthenticationSource</strong> for our application as shown 
below:</p>
			<p class="translation">
				如果我们想要使用 LDAP 认证，那么我们首先要将 <a href="https://www.nuget.org/packages/Abp.Zero.Ldap" target="_blank">Abp.Zero.Ldap</a> nuget 包添加到项目中（通常添加到 Core（领域）项目）。
				然后，我们应该为应用程序扩展 <strong>LdapAuthenticationSource</strong>，如下所示：
			</p>
			<pre lang="cs">public class MyLdapAuthenticationSource : LdapAuthenticationSource&lt;Tenant, User&gt;
{
    public MyLdapAuthenticationSource(ILdapSettings settings, IAbpZeroLdapModuleConfig ldapModuleConfig)
        : base(settings, ldapModuleConfig)
    {
    }
}</pre>
			<p>Lastly, we should set a module dependency to <strong>AbpZeroLdapModule</strong> 
and <strong>enable</strong> LDAP with the auth source created above:</p>
			<p class="translation">
				最后，我们应该设置 AbpZeroLdapModule 的模块依赖，然后启用上面创建的 LDAP 认证源：
			</p>
			<pre lang="cs">
<strong>[DependsOn(typeof(AbpZeroLdapModule))]</strong>
public class MyApplicationCoreModule : AbpModule
{
    public override void PreInitialize()
    {
        <strong>Configuration.Modules.ZeroLdap().Enable(typeof (MyLdapAuthenticationSource));</strong>    
    }

    ...
}</pre>
			<p>After these steps, LDAP module will be enabled for your application. But 
	LDAP auth is not enabled by default. We can enable it using settings.</p>
			<p class="translation">
				经过这些步骤之后，你的应用程序就启用了 LDAP 模块。但是 LDAP 认证在默认情况下没有开启的。我们可以使用设置来开启它。
			</p>

			<h5>Settings - 设置</h5>
			<p>
				<strong>LdapSettingNames</strong> class defines constants for setting names. You can use these 
constant names while changing settings (or getting settings). LDAP settings 
are <strong>per tenant</strong> (for multi-tenant applications). So, different tenants have 
different settings (see setting definitions on
				<a href="https://github.com/aspnetboilerplate/module-zero/blob/master/src/Abp.Zero.Ldap/Ldap/Configuration/LdapSettingProvider.cs" target="_blank">
github</a>).&nbsp;</p>
			<p class="translation">
				<strong>LdapSettingNames</strong> 类定义了一些设置名称的常量。当要改变设置（或者获取设置）时，你可以使用这些常量名称。
				LDAP 设置是针对<strong>每个租户</strong>的（对于多租户应用）。
				因此，不同的租户有不同的设置（请参见 <a href="https://gitee.com/HQYCODE/aspnetboilerplate/blob/master-cn/src/Abp.Zero.Ldap/Ldap/Configuration/LdapSettingProvider.cs" target="_blank">gitee</a> 上设置的定义）。
			</p>
			<p>As you can see in the MyLdapAuthenticationSource<strong> constructor</strong>, LdapAuthenticationSource expects
				<strong>ILdapSettings</strong> as a constructor argument. This interface is used 
to get LDAP settings like domain, user name and password to connect to Active 
Directory. Default implementation (<strong>LdapSettings</strong> class) gets these settings from 
the <a href="/Pages/Documents/Setting-Management">setting manager</a>.</p>
			<p class="translation">
				正如你在 MyLdapAuthenticationSource 的<strong>构造函数</strong>中看到的，LdapAuthenticationSource 期望 <strong>ILdapSettings</strong> 作为构造函数参数。
				这个接口用于获得 LDAP 设置，如域，用户名和密码，以连接到 Active Directory。
				默认的实现（<strong>LdapSetting</strong> 类）从<a href="../Setting-Management.html">设置管理器</a>中获得这些设置。
			</p>
			<p>If you work with Setting manager, then no problem. You can change LDAP 
	settings using <a href="/Pages/Documents/Setting-Management">setting manager 
	API</a>. If you want, you can add an initial/seed data to database to enable 
	LDAP auth by default.</p>
			<p class="translation">
				如果你使用了设置管理器，那么就没有问题了。你可以使用设置<a href="../Setting-Management.html">管理器 API</a> 改变 LDAP 的设置。
				如果你想要的话，你可以通过将一个 initial/seed 数据添加到数据库来默认启用 LDAP 认证。
			</p>
			<p>Note: If you don't define domain, username and password, LDAP authentication works for current 
domain if your application runs in a domain with appropriate privileges.</p>
			<p class="translation">
				注意：如果你没有定义域，用户名和密码，且你的应用程序运行在具有合适权限的域中，那么 LDAP 认证只对当前的域有效。
			</p>
			<h5>Custom Settings - 自定义设置</h5>
			<p>If you want to define 
	another setting source, you can implement a custom ILdapSettings class as 
	shown below:</p>
			<p class="translation">
				如果你想定义其他的设置源，那么你可以实现一个自定义的 ILdapSettings 类，如下所示：
			</p>
			<pre lang="cs">public class MyLdapSettings : <strong>ILdapSettings</strong>
{
    public async Task&lt;bool&gt; GetIsEnabled(int? tenantId)
    {
        return true;
    }

    public async Task&lt;ContextType&gt; GetContextType(int? tenantId)
    {
        return ContextType.Domain;
    }

    public async Task&lt;string&gt; GetContainer(int? tenantId)
    {
        return null;
    }

    public async Task&lt;string&gt; GetDomain(int? tenantId)
    {
        return null;
    }

    public async Task&lt;string&gt; GetUserName(int? tenantId)
    {
        return null;
    }

    public async Task&lt;string&gt; GetPassword(int? tenantId)
    {
        return null;
    }
}</pre>
			<p>And register it to IOC in PreInitialize of your module:</p>
			<p class="translation">然后在模块的 PreInitialize 中将它注册到 IOC：</p>
			<pre lang="cs">[DependsOn(typeof(AbpZeroLdapModule))]
public class MyApplicationCoreModule : AbpModule
{
    public override void PreInitialize()
    {
        <strong>IocManager.Register&lt;ILdapSettings, MyLdapSettings&gt;(); //change default setting source</strong>
        Configuration.Modules.ZeroLdap().Enable(typeof (MyLdapAuthenticationSource));
    }

    ...
}</pre>

			<p>Then you can get LDAP settings from any other source.</p>
			<p class="translation">这样你就可以从任何其它源获取 LDAP 设置。</p>
			<h4>Social Logins</h4>
			<p>See <a href="Startup-Template.html">startup template</a> document 
			for social logins.</p>

		</div>

	</body>

</html>
